/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pa165.dominatingspecies.frontend.animal;

import java.util.ArrayList;
import java.util.List;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.springframework.dao.DataAccessException;
import org.springframework.security.access.prepost.PreAuthorize;
import pa165.dominating.species.service.AnimalService;
import pa165.dominating.species.tos.AnimalTo;
import pa165.dominating.species.tos.EnvironmentTo;
import pa165.dominatingspecies.frontend.pages.BasePage;

/**
 *
 * @author Filip
 */
@PreAuthorize("hasRole('WORKER')")
public class AnimalPreyPredatorsPage extends BasePage {

    @SpringBean(name = "animalService")
    private AnimalService animalService;
    private AnimalTo source;
    private AnimalTo target;
    private EnvironmentTo filter = null;
    private boolean manipulatingPrey; // true - add/remove prey, false - add/remove predator

    public AnimalPreyPredatorsPage(Long id, EnvironmentTo environment, boolean manipulatingPrey) {
        filter = environment;
        this.manipulatingPrey = manipulatingPrey;
        setPage(id);
    }

    private void setPage(Long id) {
        if (id != null) {
            source = animalService.getAnimalById(id);
        }

        add(new Label("identif", source.getId().toString()));
        add(new Label("nameLabel", source.getName()));
        add(new Label("speciesLabel", source.getSpecies()));
        if (manipulatingPrey) {
            add(new Label("preyPredatorsLabel", new StringResourceModel("preyOfAnimal", this, null).getString()));
        } else {
            add(new Label("preyPredatorsLabel", new StringResourceModel("predatorsOfAnimal", this, null).getString()));
        }

        ListView<AnimalTo> listView = new View("listview", createModel());
        add(listView);

        Link<BasePage> goBack = new Link<BasePage>("goBack") {
            @Override
            public void onClick() {
                setResponsePage(new AnimalsPage(filter));
            }
        };
        add(goBack);

        Form<AnimalPreyPredatorsPage> createForm = new Form<>("addPreyPredatorForm",
                new CompoundPropertyModel<>(this));
        add(createForm);
        List<AnimalTo> animals = animalService.getAllAnimals();
        createForm.add(new DropDownChoice<>("animals", new PropertyModel<AnimalTo>(this, "target"), animals));

        Button submitButton = new Button("submitButton") {
            @Override
            public void onSubmit() {
                boolean errorsFound = false;
                if (target == null) {
                    if (manipulatingPrey) {
                        getSession().warn(new StringResourceModel("animalNoPreySelectedWarn", this, null).getString());
                    } else {
                        getSession().warn(new StringResourceModel("animalNoPrdatorSelectedWarn", this, null).getString());
                    }
                    setResponsePage(new AnimalPreyPredatorsPage(source.getId(), filter, manipulatingPrey));
                    errorsFound = true;
                }

                if (!errorsFound) {
                    boolean thrown = false;
                    boolean contains = false;
                    try {
                        List<AnimalTo> list;
                        if (manipulatingPrey) {
                            list = animalService.getPreyOfPredator(source);
                        } else {
                            list = animalService.getPredatorsOfPrey(source);
                        }

                        for (AnimalTo anim : list) {
                            if (anim.getId() == target.getId()) {
                                contains = true;
                                break;
                            }
                        }
                        if (!contains) {
                            if (manipulatingPrey) {
                                animalService.addPreyToPredator(source, target);
                            } else {
                                animalService.addPreyToPredator(target, source);
                            }
                        }
                    } catch (DataAccessException e) {
                        if (manipulatingPrey) {
                            getSession().warn(new StringResourceModel("addPreyFail", this, null, new Object[]{target.getId()}).getString());
                        } else {
                            getSession().warn(new StringResourceModel("addPredatorFail", this, null, new Object[]{target.getId()}).getString());
                        }

                        System.out.println(e.getMessage());
                        setResponsePage(new AnimalPreyPredatorsPage(source.getId(), filter, manipulatingPrey));
                        thrown = true;
                    }
                    if (!thrown) {
                        if (!contains) {
                            if (manipulatingPrey) {
                                getSession().info(new StringResourceModel("preyAddedSucc", this, null, new Object[]{target.getId()}).getString());
                            } else {
                                getSession().info(new StringResourceModel("predatorAddedSucc", this, null, new Object[]{target.getId()}).getString());
                            }

                            setResponsePage(new AnimalPreyPredatorsPage(source.getId(), filter, manipulatingPrey));
                        } else {
                            if (manipulatingPrey) {
                                getSession().warn(new StringResourceModel("preyAlreadyContained", this, null, new Object[]{target.getId()}).getString());
                            } else {
                                getSession().warn(new StringResourceModel("predatorAlreadyContained", this, null, new Object[]{target.getId()}).getString());
                            }
                        }
                    }
                }
            }
        };
        createForm.add(submitButton);
        if (manipulatingPrey) {
            createForm.add(new Label("addPreyPredatorLabel", new StringResourceModel("addPrey", this, null)));
        } else {
            createForm.add(new Label("addPreyPredatorLabel", new StringResourceModel("addPredator", this, null)));
        }

    }

    private LoadableDetachableModel<List<AnimalTo>> createModel() {

        return new LoadableDetachableModel<List<AnimalTo>>() {
            @Override
            protected List<AnimalTo> load() {
                List<AnimalTo> list = new ArrayList<>();
                if (manipulatingPrey) {
                    list = animalService.getPreyOfPredator(source);
                } else {
                    list = animalService.getPredatorsOfPrey(source);
                }

                return list;
            }
        };
    }

    private class View extends ListView<AnimalTo> {

        protected View(String s, LoadableDetachableModel<List<AnimalTo>> model) {
            super(s, model);
        }

        @Override
        protected void populateItem(ListItem<AnimalTo> item) {
            item.add(new Label("id", new PropertyModel(item.getModel(), "id")));
            item.add(new Label("name", new PropertyModel(item.getModel(), "name")));
            item.add(new Label("species", new PropertyModel(item.getModel(), "species")));
            final AnimalTo target = (AnimalTo) item.getModelObject();
            item.add(new RemoveAnimalLink("remove", source, target, filter, manipulatingPrey));
        }
    }
}
